package com.tico.common.utils.tree;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author liufm
 * @date 2020/8/4 8:50
 */
public class TreeUtils {
    private static TreeUtils instance = new TreeUtils();

    private TreeUtils() {
    }

    public static TreeUtils getInstance() {
        return instance;
    }

    public <T> Object getTree(List<T> tList, Class c) {
        T ts = null;
        Object return_data = null;
        HashMap<Serializable, List<T>> map = new HashMap<>();
        System.out.println(c.getName());
        TreeL annotationField = (TreeL) c.getAnnotation(TreeL.class);
        if (annotationField != null) {
            System.out.println("annotationField : " + annotationField);
            String parentField = annotationField.parentField();
            String parentValue = annotationField.parentValue();
            String childrenField = annotationField.childrenField();
            String identification = annotationField.identification();
            List<T> list = null;
            for (T t : tList) {
                try {
                    Class<?> aClass = t.getClass();
                    Method m = aClass.getMethod("get" + parentField);
                    Serializable v = (String) m.invoke(t);
                    if (v != null) {
                        list = (List<T>) map.get(v);
                        if (list == null) {
                            list = new ArrayList<T>();
                        }
                        list.add(t);
                        map.put(v, list);
                        if (v.equals(parentValue)) {
                            ts = t;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            try {
                return_data = creatTree(ts, map, identification, childrenField);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return return_data;
    }

    public <T> T creatTree(T t, HashMap<Serializable, List<T>> myMultimap, String identification, String childrenField) {
        Class<?> aClass = t.getClass();
        try {
            Method m = aClass.getMethod("get" + identification);
            Serializable v = (String) m.invoke(t);
            if (myMultimap.get(v) != null) {
                List<T> tIotLocations = myMultimap.get(v);
                recursionData(tIotLocations, myMultimap, identification, childrenField);
                Method m2 = aClass.getMethod("set" + childrenField, List.class);
                m2.invoke(t, tIotLocations);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return t;
    }

    public <T> void recursionData(List<T> tIotLocations, HashMap<Serializable, List<T>> myMultimap, String childField, String childrenField) {
        for (T t : tIotLocations) {
            Class<?> aClass = t.getClass();
            try {
                Method mq = aClass.getMethod("get" + childField);
                Serializable m = (String) mq.invoke(t);
                if (myMultimap.get(m) != null) {
                    List<T> tt = myMultimap.get(m);
                    recursionData(tt, myMultimap, childField, childrenField);
                    Method m2 = aClass.getMethod("set" + childrenField, List.class);
                    try {
                        m2.invoke(t, tt);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

        }
    }
}
